using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using BanZuiCloudControlAgent.Utils.Logging;

namespace BanZuiCloudControlAgent.Extensions.QQ
{
    /// <summary>
    /// QQTools.dll的封装类，提供对QQ内部功能的访问
    /// </summary>
    public static class QQWrapper
    {
        private static readonly Logger _logger = LogManager.GetLogger(nameof(QQWrapper));
        
        /// <summary>
        /// QQTools.dll的导入类，用于导入dll中的方法
        /// </summary>
        private static class QQDLL
        {
            const string dllPath = "Libs/QQTools.dll";
            
            /// <summary>
            /// 根据PID从内存获取获取客户端key 长度64位 此Key权限最高  
            /// </summary>
            /// <param name="pid">QQ进程ID</param>
            /// <returns>客户端key的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetClientKey(int pid);

            /// <summary>
            /// 根据QQ号和PID获取昵称
            /// </summary>
            /// <param name="Uin">QQ号</param>
            /// <param name="pid">QQ进程ID</param>
            /// <returns>昵称的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetClientName(string Uin, int pid);

            /// <summary>
            /// 获取指定QQ进程登陆的QQ号
            /// </summary>
            /// <param name="pid">QQ进程ID</param>
            /// <returns>QQ号的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetClientSelfUin(int pid);

            /// <summary>
            /// 用ClentKey从内存获取Cookie
            /// </summary>
            /// <param name="Uin">QQ号</param>
            /// <param name="Clientkey">客户端key</param>
            /// <returns>Cookie的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetCookieByClentKey(string Uin, string Clientkey);

            /// <summary>
            /// 用HttpKey从内存获取Cookie
            /// </summary>
            /// <param name="Uin">QQ号</param>
            /// <param name="HttpKey">Http key</param>
            /// <returns>Cookie的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetCookieByHttpKey(string Uin, string HttpKey);

            /// <summary>
            /// 用ClentKey从内存获取QzoneCookie
            /// </summary>
            /// <param name="Uin">QQ号</param>
            /// <param name="Clientkey">客户端key</param>
            /// <returns>QzoneCookie的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetQzoneCookieByClentKey(string Uin, string Clientkey);

            /// <summary>
            /// 用HttpKey从内存获取QzoneCookie
            /// </summary>
            /// <param name="Uin">QQ号</param>
            /// <param name="HttpKey">Http key</param>
            /// <returns>QzoneCookie的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetQzoneCookieByHttpKey(string Uin, string HttpKey);

            /// <summary>
            /// 可用于 bkn，gtk，ldw计算
            /// </summary>
            /// <param name="Skey">Skey 或者P_Skey</param>
            /// <param name="Type">0-整数型，1-MD5型</param>
            /// <returns>计算结果的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetGtkBySkey(string Skey, int Type);

            /// <summary>
            /// 从内存获取网页登陆的key 长度224位
            /// </summary>
            /// <param name="pid">QQ进程ID</param>
            /// <returns>Http key的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetHttpkey(int pid);

            /// <summary>
            /// 从内存判断指定QQ是否在线
            /// </summary>
            /// <param name="Uin">QQ号</param>
            /// <param name="pid">QQ进程ID</param>
            /// <returns>在线状态的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr IsOnline(string Uin, int pid);

            /// <summary>
            /// 根据PID从内存获取群列表
            /// </summary>
            /// <param name="pid">QQ进程ID</param>
            /// <returns>群列表的指针</returns>
            [DllImport(dllPath, CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr GetGroupList(int pid);
        }

        #region 公共方法

        /// <summary>
        /// 根据进程ID获取QQ号
        /// </summary>
        /// <param name="pid">QQ进程ID</param>
        /// <returns>QQ号，获取失败返回null</returns>
        public static string GetQQNumber(int pid)
        {
            try
            {
                _logger.Info($"[GetQQNumber] 获取QQ号被调用 Pid:{pid}");
                IntPtr resultPtr = QQDLL.GetClientSelfUin(pid);
                string qqNumber = Marshal.PtrToStringAnsi(resultPtr);
                
                if (string.IsNullOrEmpty(qqNumber))
                {
                    _logger.Warn($"[GetQQNumber] 获取QQ号失败 Pid:{pid}");
                    return null;
                }
                
                _logger.Info($"[GetQQNumber] 获取QQ号成功 Pid:{pid}, QQ:{qqNumber}");
                return qqNumber;
            }
            catch (Exception ex)
            {
                _logger.Error($"[GetQQNumber] 获取QQ号异常 Pid:{pid}", ex);
                return null;
            }
        }

        /// <summary>
        /// 根据QQ号和进程ID获取昵称
        /// </summary>
        /// <param name="qq">QQ号</param>
        /// <param name="pid">QQ进程ID</param>
        /// <returns>QQ昵称，获取失败返回null</returns>
        public static string GetNickname(string qq, int pid)
        {
            try
            {
                _logger.Info($"[GetNickname] 获取QQ昵称被调用 QQ:{qq} Pid:{pid}");
                
                if (string.IsNullOrEmpty(qq) || pid <= 0)
                {
                    _logger.Error($"[GetNickname] 获取QQ昵称参数错误 QQ:{qq} Pid:{pid}");
                    return null;
                }
                
                IntPtr resultPtr = QQDLL.GetClientName(qq, pid);
                string nickname = Marshal.PtrToStringAnsi(resultPtr);
                
                if (string.IsNullOrEmpty(nickname))
                {
                    _logger.Warn($"[GetNickname] 获取QQ昵称失败 QQ:{qq} Pid:{pid}");
                    return null;
                }
                
                _logger.Info($"[GetNickname] 获取QQ昵称成功 QQ:{qq} Pid:{pid}, 昵称:{nickname}");
                return nickname;
            }
            catch (Exception ex)
            {
                _logger.Error($"[GetNickname] 获取QQ昵称异常 QQ:{qq} Pid:{pid}", ex);
                return null;
            }
        }

        /// <summary>
        /// 根据进程ID获取客户端key
        /// </summary>
        /// <param name="pid">QQ进程ID</param>
        /// <returns>客户端key，获取失败返回null</returns>
        public static string GetClientKey(int pid)
        {
            try
            {
                _logger.Info($"[GetClientKey] 获取客户端key被调用 Pid:{pid}");
                IntPtr resultPtr = QQDLL.GetClientKey(pid);
                string clientKey = Marshal.PtrToStringAnsi(resultPtr);
                
                if (string.IsNullOrEmpty(clientKey))
                {
                    _logger.Warn($"[GetClientKey] 获取客户端key失败 Pid:{pid}");
                    return null;
                }
                
                _logger.Info($"[GetClientKey] 获取客户端key成功 Pid:{pid}");
                return clientKey;
            }
            catch (Exception ex)
            {
                _logger.Error($"[GetClientKey] 获取客户端key异常 Pid:{pid}", ex);
                return null;
            }
        }

        /// <summary>
        /// 根据进程ID获取Http key
        /// </summary>
        /// <param name="pid">QQ进程ID</param>
        /// <returns>Http key，获取失败返回null</returns>
        public static string GetHttpKey(int pid)
        {
            try
            {
                _logger.Info($"[GetHttpKey] 获取Http key被调用 Pid:{pid}");
                IntPtr resultPtr = QQDLL.GetHttpkey(pid);
                string httpKey = Marshal.PtrToStringAnsi(resultPtr);
                
                if (string.IsNullOrEmpty(httpKey))
                {
                    _logger.Warn($"[GetHttpKey] 获取Http key失败 Pid:{pid}");
                    return null;
                }
                
                _logger.Info($"[GetHttpKey] 获取Http key成功 Pid:{pid}");
                return httpKey;
            }
            catch (Exception ex)
            {
                _logger.Error($"[GetHttpKey] 获取Http key异常 Pid:{pid}", ex);
                return null;
            }
        }

        /// <summary>
        /// 判断QQ是否在线
        /// </summary>
        /// <param name="qq">QQ号</param>
        /// <param name="pid">QQ进程ID</param>
        /// <returns>是否在线，获取失败返回false</returns>
        public static bool IsOnline(string qq, int pid)
        {
            try
            {
                _logger.Info($"[IsOnline] 判断QQ是否在线被调用 QQ:{qq} Pid:{pid}");
                
                if (string.IsNullOrEmpty(qq) || pid <= 0)
                {
                    _logger.Error($"[IsOnline] 判断QQ是否在线参数错误 QQ:{qq} Pid:{pid}");
                    return false;
                }
                
                IntPtr resultPtr = QQDLL.IsOnline(qq, pid);
                // 在线 resultPtr 0x00000001 离线 resultPtr 0x00000000
                bool isOnline = resultPtr != IntPtr.Zero;
                
                _logger.Info($"[IsOnline] QQ:{qq} Pid:{pid} 在线状态:{isOnline}");
                return isOnline;
            }
            catch (Exception ex)
            {
                _logger.Error($"[IsOnline] 判断QQ是否在线异常 QQ:{qq} Pid:{pid}", ex);
                return false;
            }
        }

        /// <summary>
        /// 根据进程ID获取群列表
        /// </summary>
        /// <param name="pid">QQ进程ID</param>
        /// <returns>群号列表，获取失败返回空列表</returns>
        public static List<string> GetGroupList(int pid)
        {
            try
            {
                _logger.Info($"[GetGroupList] 获取群列表被调用 Pid:{pid}");
                IntPtr resultPtr = QQDLL.GetGroupList(pid);
                string groupListStr = Marshal.PtrToStringAnsi(resultPtr);
                List<string> groupList = new List<string>();
                
                // 使用逗号分割群号
                if (!string.IsNullOrEmpty(groupListStr))
                {
                    groupList = groupListStr.Split(',')
                        .Where(g => !string.IsNullOrEmpty(g))
                        .ToList();
                }
                
                _logger.Info($"[GetGroupList] 获取群列表成功 Pid:{pid}, 群数量:{groupList.Count}");
                return groupList;
            }
            catch (Exception ex)
            {
                _logger.Error($"[GetGroupList] 获取群列表异常 Pid:{pid}", ex);
                return new List<string>();
            }
        }

        /// <summary>
        /// 获取Cookie
        /// </summary>
        /// <param name="qq">QQ号</param>
        /// <param name="pid">QQ进程ID</param>
        /// <returns>Cookie，获取失败返回null</returns>
        public static string GetCookie(string qq, int pid)
        {
            try
            {
                _logger.Info($"[GetCookie] 获取Cookie被调用 QQ:{qq} Pid:{pid}");
                
                if (string.IsNullOrEmpty(qq) || pid <= 0)
                {
                    _logger.Error($"[GetCookie] 获取Cookie参数错误 QQ:{qq} Pid:{pid}");
                    return null;
                }
                
                // 先尝试使用ClientKey获取
                string clientKey = GetClientKey(pid);
                if (!string.IsNullOrEmpty(clientKey))
                {
                    IntPtr resultPtr = QQDLL.GetCookieByClentKey(qq, clientKey);
                    string cookie = Marshal.PtrToStringAnsi(resultPtr);
                    
                    if (!string.IsNullOrEmpty(cookie))
                    {
                        _logger.Info($"[GetCookie] 使用ClientKey获取Cookie成功 QQ:{qq} Pid:{pid}");
                        return cookie;
                    }
                }
                
                // 如果ClientKey获取失败，尝试使用HttpKey获取
                string httpKey = GetHttpKey(pid);
                if (!string.IsNullOrEmpty(httpKey))
                {
                    IntPtr resultPtr = QQDLL.GetCookieByHttpKey(qq, httpKey);
                    string cookie = Marshal.PtrToStringAnsi(resultPtr);
                    
                    if (!string.IsNullOrEmpty(cookie))
                    {
                        _logger.Info($"[GetCookie] 使用HttpKey获取Cookie成功 QQ:{qq} Pid:{pid}");
                        return cookie;
                    }
                }
                
                _logger.Warn($"[GetCookie] 获取Cookie失败 QQ:{qq} Pid:{pid}");
                return null;
            }
            catch (Exception ex)
            {
                _logger.Error($"[GetCookie] 获取Cookie异常 QQ:{qq} Pid:{pid}", ex);
                return null;
            }
        }

        /// <summary>
        /// 获取QzoneCookie
        /// </summary>
        /// <param name="qq">QQ号</param>
        /// <param name="pid">QQ进程ID</param>
        /// <returns>QzoneCookie，获取失败返回null</returns>
        public static string GetQzoneCookie(string qq, int pid)
        {
            try
            {
                _logger.Info($"[GetQzoneCookie] 获取QzoneCookie被调用 QQ:{qq} Pid:{pid}");
                
                if (string.IsNullOrEmpty(qq) || pid <= 0)
                {
                    _logger.Error($"[GetQzoneCookie] 获取QzoneCookie参数错误 QQ:{qq} Pid:{pid}");
                    return null;
                }
                
                // 先尝试使用ClientKey获取
                string clientKey = GetClientKey(pid);
                if (!string.IsNullOrEmpty(clientKey))
                {
                    IntPtr resultPtr = QQDLL.GetQzoneCookieByClentKey(qq, clientKey);
                    string cookie = Marshal.PtrToStringAnsi(resultPtr);
                    
                    if (!string.IsNullOrEmpty(cookie))
                    {
                        _logger.Info($"[GetQzoneCookie] 使用ClientKey获取QzoneCookie成功 QQ:{qq} Pid:{pid}");
                        return cookie;
                    }
                }
                
                // 如果ClientKey获取失败，尝试使用HttpKey获取
                string httpKey = GetHttpKey(pid);
                if (!string.IsNullOrEmpty(httpKey))
                {
                    IntPtr resultPtr = QQDLL.GetQzoneCookieByHttpKey(qq, httpKey);
                    string cookie = Marshal.PtrToStringAnsi(resultPtr);
                    
                    if (!string.IsNullOrEmpty(cookie))
                    {
                        _logger.Info($"[GetQzoneCookie] 使用HttpKey获取QzoneCookie成功 QQ:{qq} Pid:{pid}");
                        return cookie;
                    }
                }
                
                _logger.Warn($"[GetQzoneCookie] 获取QzoneCookie失败 QQ:{qq} Pid:{pid}");
                return null;
            }
            catch (Exception ex)
            {
                _logger.Error($"[GetQzoneCookie] 获取QzoneCookie异常 QQ:{qq} Pid:{pid}", ex);
                return null;
            }
        }

  

        #endregion
    }
} 